package com.zhouyu.mybatis.mybatis;

import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
import org.springframework.core.type.classreading.MetadataReader;

import java.io.IOException;
import java.util.Objects;
import java.util.Set;

import static org.springframework.beans.factory.support.AbstractBeanDefinition.AUTOWIRE_BY_TYPE;

/**
 * @author by gang.Li 2022/4/7 16:03
 */
public class MyBatisMapperScanner extends ClassPathBeanDefinitionScanner {

	public MyBatisMapperScanner(BeanDefinitionRegistry registry) {
		super(registry);
	}

	/**
	 * 将所有的类 否返回,包括接口类型
	 *
	 * @param metadataReader the ASM ClassReader for the class
	 * @return boolean
	 * @throws IOException IOException
	 */
	@Override
	protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
		return true;
	}

	/**
	 * 将生成的beanDefinition 判断 返回的结果都为true
	 *
	 * @param beanDefinition the bean definition to check
	 * @return boolean
	 */
	@Override
	protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
		return true;
	}

	/**
	 * 重写doScan方法,实现接口类型的beanDefinition 设置为代理类
	 *
	 * @param basePackages the packages to check for annotated classes
	 * @return Set<BeanDefinitionHolder>
	 */
	@Override
	protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
		Set<BeanDefinitionHolder> beanDefinitionHolders = super.doScan(basePackages);
		beanDefinitionHolders.forEach(beanDefinitionHolder -> {
			GenericBeanDefinition beanDefinition = (GenericBeanDefinition) beanDefinitionHolder.getBeanDefinition();
			// 设置 推断构造入参
			beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(Objects.requireNonNull(beanDefinition.getBeanClassName()));
			beanDefinition.setBeanClassName(MybatisFactoryBean.class.getName());
			// 将自动注入设置为bytype
			beanDefinition.setAutowireMode(AUTOWIRE_BY_TYPE);
		});
		return beanDefinitionHolders;
	}
}
